/*
 * Module.h
 *
 *  Created on: Jul 12, 2012
 *      Author: luporini
 */

#ifndef MODULE_H_
#define MODULE_H_

#include <iostream>
using namespace std;

#include <pthread.h>
#include "Queue.h"

enum stream_t {
	STREAM_A,
	STREAM_B
};

template <class T, class K>
class Module {
private:
	pthread_t 		thread;

public:
	TupleQueue<T> 	*rowQueue;
	TupleQueue<K> 	*colQueue;

	inline Module() {}

	/** Returns true if the module was successfully started, false if there was an error starting the module */
    bool startModule (TupleQueue<T> *_rowQueue, TupleQueue<K> *_colQueue, unsigned int cpuID)
    {
    	//starting module
    	if (pthread_create(&thread, NULL, moduleCode, this) == 0)
    		return false;

    	rowQueue = _rowQueue;
    	colQueue = _colQueue;

    	return true;
    }
    bool waitModule ()
    {
    	//waits for the associated thread to terminate
		(void) pthread_join(thread, NULL);
    }



	inline ~Module ()
	{
		delete rowQueue;
		delete colQueue;
	}

protected:
	/** Implement this method in your subclass with the code you want your thread to run. */
	virtual void run() = 0;

	// Reads randomly from one of the input queues. It's a blocking function, i.e. the caller waits until at least one element has been read.
	T* alternative ( int* size, stream_t* queueID )
	{
		//TODO: up to now it is deterministic, rather than alternative xD
		*queueID = STREAM_A;
		*size = 1;
		return rowQueue->pop();
	}


private:
	inline static void * moduleCode(void * This)
	{
		reinterpret_cast<Module *> (This)->run(); //OMFG
		return NULL;
	}

};

#endif /* MODULE_H_ */
